import java.io.*;
import java.net.*;
import java.util.concurrent.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import com.google.gson.JsonObject;

/**
 * 自定义TCP套接字天气服务器
 * 当API服务不可用时，提供基本的天气数据作为备份源
 */
public class SocketWeatherServer {
    private static final int DEFAULT_PORT = 8888;
    private ServerSocket serverSocket;
    private boolean running = false;
    private ExecutorService clientThreadPool;
    
    public SocketWeatherServer() {
        this(DEFAULT_PORT);
    }
    
    public SocketWeatherServer(int port) {
        try {
            serverSocket = new ServerSocket(port);
            clientThreadPool = Executors.newFixedThreadPool(10);
            System.out.println("Socket Weather Server started on port " + port);
        } catch (IOException e) {
            System.err.println("Failed to start socket server on port " + port + ": " + e.getMessage());
        }
    }
    
    public void start() {
        if (serverSocket == null) return;
        
        running = true;
        new Thread(() -> {
            while (running) {
                try {
                    Socket clientSocket = serverSocket.accept();
                    clientThreadPool.submit(new ClientHandler(clientSocket));
                } catch (IOException e) {
                    if (running) {
                        System.err.println("Error accepting client connection: " + e.getMessage());
                    }
                }
            }
        }).start();
        
        System.out.println("Socket Weather Server is running and accepting connections");
    }
    
    public void stop() {
        running = false;
        try {
            if (serverSocket != null && !serverSocket.isClosed()) {
                serverSocket.close();
            }
            if (clientThreadPool != null) {
                clientThreadPool.shutdown();
                clientThreadPool.awaitTermination(5, TimeUnit.SECONDS);
            }
            System.out.println("Socket Weather Server stopped");
        } catch (IOException | InterruptedException e) {
            System.err.println("Error stopping server: " + e.getMessage());
        }
    }
    
    public boolean isRunning() {
        return running && serverSocket != null && !serverSocket.isClosed();
    }
    
    public int getPort() {
        return serverSocket != null ? serverSocket.getLocalPort() : -1;
    }
    
    /**
     * 客户端处理器
     */
    private static class ClientHandler implements Runnable {
        private Socket clientSocket;
        
        public ClientHandler(Socket socket) {
            this.clientSocket = socket;
        }
        
        @Override
        public void run() {
            try (BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                 PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true)) {
                
                String request = in.readLine();
                System.out.println("Received request: " + request);
                
                if (request != null) {
                    String response = handleRequest(request);
                    out.println(response);
                    System.out.println("Sent response: " + response);
                }
                
            } catch (IOException e) {
                System.err.println("Error handling client: " + e.getMessage());
            } finally {
                try {
                    clientSocket.close();
                } catch (IOException e) {
                    System.err.println("Error closing client socket: " + e.getMessage());
                }
            }
        }
        
        /**
         * 处理客户端请求并生成模拟天气数据
         */
        private String handleRequest(String request) {
            try {
                // 解析请求 (格式: "WEATHER:CITY_NAME" 或 "FORECAST:CITY_NAME:DAYS")
                String[] parts = request.split(":");
                
                if (parts.length < 2) {
                    return createErrorResponse("Invalid request format");
                }
                
                String command = parts[0].toUpperCase();
                String cityName = parts[1];
                
                switch (command) {
                    case "WEATHER":
                        return generateCurrentWeatherData(cityName);
                    case "FORECAST":
                        int days = parts.length > 2 ? Integer.parseInt(parts[2]) : 3;
                        return generateForecastData(cityName, days);
                    case "TEST":
                        return "PONG";
                    default:
                        return createErrorResponse("Unknown command: " + command);
                }
                
            } catch (Exception e) {
                return createErrorResponse("Error processing request: " + e.getMessage());
            }
        }
        
        /**
         * 生成模拟的当前天气数据
         */
        private String generateCurrentWeatherData(String cityName) {
            JsonObject response = new JsonObject();
            JsonObject main = new JsonObject();
            JsonObject wind = new JsonObject();
            
            // 生成基于城市名称的模拟数据（保持一致性）
            long seed = cityName.hashCode();
            java.util.Random random = new java.util.Random(seed);
            
            // 温度范围：-10°C 到 35°C
            double temperature = -10 + random.nextDouble() * 45;
            double humidity = 30 + random.nextDouble() * 60; // 30-90%
            double windSpeed = random.nextDouble() * 15; // 0-15 m/s
            
            main.addProperty("temp", Math.round(temperature * 10.0) / 10.0);
            main.addProperty("humidity", Math.round(humidity));
            wind.addProperty("speed", Math.round(windSpeed * 10.0) / 10.0);
            
            response.addProperty("source", "socket-backup");
            response.addProperty("city", cityName);
            response.addProperty("description", getWeatherDescription(temperature));
            response.addProperty("timestamp", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
            response.add("main", main);
            response.add("wind", wind);
            
            return response.toString();
        }
        
        /**
         * 生成模拟的预报数据
         */
        private String generateForecastData(String cityName, int days) {
            JsonObject response = new JsonObject();
            com.google.gson.JsonArray forecastArray = new com.google.gson.JsonArray();
            
            long seed = cityName.hashCode();
            java.util.Random random = new java.util.Random(seed);
            
            for (int i = 0; i < days; i++) {
                JsonObject dayForecast = new JsonObject();
                JsonObject main = new JsonObject();
                JsonObject wind = new JsonObject();
                
                // 生成每日变化的数据
                double baseTemp = -5 + random.nextDouble() * 35;
                double temperature = baseTemp + (random.nextDouble() - 0.5) * 10;
                double humidity = 35 + random.nextDouble() * 50;
                double windSpeed = random.nextDouble() * 12;
                
                main.addProperty("temp", Math.round(temperature * 10.0) / 10.0);
                main.addProperty("humidity", Math.round(humidity));
                wind.addProperty("speed", Math.round(windSpeed * 10.0) / 10.0);
                
                dayForecast.addProperty("date", LocalDateTime.now().plusDays(i).format(DateTimeFormatter.ISO_LOCAL_DATE));
                dayForecast.addProperty("description", getWeatherDescription(temperature));
                dayForecast.add("main", main);
                dayForecast.add("wind", wind);
                
                forecastArray.add(dayForecast);
            }
            
            response.addProperty("source", "socket-backup");
            response.addProperty("city", cityName);
            response.addProperty("timestamp", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
            response.add("forecast", forecastArray);
            
            return response.toString();
        }
        
        /**
         * 根据温度生成合适的天气描述
         */
        private String getWeatherDescription(double temperature) {
            if (temperature < 0) {
                return "Freezing conditions";
            } else if (temperature < 10) {
                return "Cold weather";
            } else if (temperature < 20) {
                return "Cool and comfortable";
            } else if (temperature < 25) {
                return "Pleasant weather";
            } else if (temperature < 30) {
                return "Warm conditions";
            } else {
                return "Hot weather";
            }
        }
        
        /**
         * 创建错误响应
         */
        private String createErrorResponse(String message) {
            JsonObject error = new JsonObject();
            error.addProperty("error", message);
            error.addProperty("timestamp", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
            return error.toString();
        }
    }
    
    /**
     * 主方法用于独立运行服务器
     */
    public static void main(String[] args) {
        int port = args.length > 0 ? Integer.parseInt(args[0]) : DEFAULT_PORT;
        SocketWeatherServer server = new SocketWeatherServer(port);
        
        // 添加关闭钩子
        Runtime.getRuntime().addShutdownHook(new Thread(server::stop));
        
        server.start();
        
        // 保持服务器运行
        try {
            Thread.currentThread().join();
        } catch (InterruptedException e) {
            server.stop();
        }
    }
} 